package com.travel.server.manager.impl.aspect;

import com.alibaba.fastjson.JSONObject;
import com.travel.common.CommonConstant;
import com.travel.common.exception.WorkCode;
import com.travel.common.exception.WorkException;
import com.travel.server.manager.impl.command.AbstractCommand;
import com.travel.server.manager.impl.controller.base.AbstractController;
import com.travel.common.base.BaseResponse;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

/**
 * @Author: LiZhenhui
 * @Date: 2018/10/17 18:04
 * @Desc:
 */
@Aspect
@Slf4j
@Component
public class CommonAspect {

    @Autowired
    private ApplicationContext ctx;

    private static final String COMMAND = "Command";

    @Pointcut("execution(* com.travel.server.manager.impl.controller.*.*(..))")
    private void pointcut() {
    }

    @Before("pointcut()")
    public void setCommand(JoinPoint joinPoint){
        String pkgClzName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        String className = pkgClzName.substring(pkgClzName.lastIndexOf(".") + 1);
        if(className.equals(CommonConstant.UPLOAD_FILE)){
            return;
        }
        char[] name = className.toCharArray();
        name[0] = Character.toLowerCase(name[0]);
        className = new String(name);

        AbstractController controller;
        try {
            controller = (AbstractController) ctx.getBean(className);
            controller.setCommand((AbstractCommand) ctx.getBean(methodName + COMMAND));
        } catch (Exception e) {
            log.error("设置方法类型异常，未查询到对应实现类 methodName{}", methodName);
            throw e;
        }
    }

    @Around("pointcut()")
    public Object handle(ProceedingJoinPoint joinPoint) throws Throwable{
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        String requestData = null;
        if(args.length > 0){
            requestData = JSONObject.toJSONString(args[0]);
        }
        Object retVal;
        try{
            retVal = joinPoint.proceed();
            log.info("类 {} 执行方法 {} 请求参数 {} 返回参数 {}", className, methodName, requestData, JSONObject.toJSONString(retVal));
            return BaseResponse.makeSuccess(retVal);
        }catch (WorkException e){
            log.info("类 {} 执行方法 {} 请求参数 {}  发生错误 message {}", className, methodName, requestData, e.getErrorMessage());
            return BaseResponse.makeError(e.getWorkCode());
        }catch (Exception e){
            log.error("类 {} 执行方法 {} 请求参数 {}  发生异常 message {}", className, methodName, requestData, e.getMessage(), e);
            return BaseResponse.makeError(WorkCode.SYSTEM);
        }
    }
}
